12-3 TypeORM同类型多数据库连接与访问配置
多数据库连接配置 🔌
命名连接必要性
每个TypeOrmModule.forRoot()
配置必须包含唯一name
属性,这是多数据库连接的基础。如果不设置name
属性,TypeORM会默认使用"default"作为连接名称,导致后续配置覆盖前面的连接。
典型错误场景:
// 错误示例:两个未命名的连接
TypeOrmModule.forRoot({ port: 3306 }), // 会被覆盖
TypeOrmModule.forRoot({ port: 3307 }) // 最终生效的连接
typescript
正确配置方式:
TypeOrmModule.forRoot({
name: 'primary_db', // 必须唯一
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '123456',
database: 'main_db'
})
typescript
💡 实际开发中建议:
- 使用业务语义化的名称(如
order_db
/user_db
) - 在大型项目中通过常量集中管理连接名称
- 配合JSDoc标注连接用途
端口差异化配置
通过不同端口连接多个同类型数据库是最常见的方案,特别适用于:
- 本地开发环境模拟多实例
- 读写分离场景
- 分库分表测试
完整配置示例:
// app.module.ts
imports: [
TypeOrmModule.forRoot({
name: 'master_db',
type: 'mysql',
port: 3306,
synchronize: false, // 生产环境必须关闭
entities: [User]
}),
TypeOrmModule.forRoot({
name: 'replica_db',
type: 'mysql',
port: 3307,
synchronize: false,
entities: [User]
})
]
typescript
连接验证方法:
# 检查连接是否生效
npm run typeorm query --query "SELECT 1" --connection master_db
npm run typeorm query --query "SELECT 1" --connection replica_db
bash
最新DataSource API
TypeORM v0.3+ 引入了更现代的DataSource
API,相比传统配置方式具有以下优势:
- 明确的生命周期管理:
const appDataSource = new DataSource({
name: 'modern_db',
type: 'mysql',
port: 3308,
// 新增的专用配置项
poolSize: 10,
logging: ['query', 'error']
});
// 显式初始化和销毁
await appDataSource.initialize();
await appDataSource.destroy();
typescript
- 连接池独立配置:
const reportDataSource = new DataSource({
name: 'report_db',
extra: {
connectionLimit: 5, // 独立连接池大小
waitForConnections: true
}
});
typescript
- 多数据源事务支持:
const queryRunner = masterDataSource.createQueryRunner();
await queryRunner.connect();
try {
await queryRunner.startTransaction();
// 跨库操作...
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
typescript
💡 迁移建议:
- 新项目直接使用DataSource API
- 已有项目逐步替换forRoot配置
- 注意v0.3+版本中Repository API的变化
混合配置方案
在实际项目中可以组合使用新旧API:
// 传统模块配置
TypeOrmModule.forRoot({ name: 'legacy_db', ... })
// 现代DataSource配置
@Module({
providers: [
{
provide: 'MODERN_DB',
useFactory: async () => {
const ds = new DataSource({...});
return await ds.initialize();
}
}
]
})
typescript
性能对比:
特性 | forRoot方式 | DataSource API |
---|---|---|
启动速度 | 较快 | 稍慢(需显式初始化) |
内存占用 | 较高 | 更低 |
连接池控制 | 有限 | 精细控制 |
TypeScript支持 | 一般 | 更好 |
多连接注入机制 ⚙️
仓库注入语法详解
在TypeORM多数据库连接场景中,@InjectRepository
装饰器的使用需要特别注意以下要点:
- 基础注入语法
@InjectRepository(entity: EntityTarget<Entity>, connectionName?: string)
typescript
entity
:目标实体类(如User)connectionName
:在forRoot
中配置的连接名称
- 完整注入示例
@Injectable()
export class AnalyticsService {
constructor(
@InjectRepository(User, 'read_db')
private readRepository: Repository<User>,
@InjectRepository(User, 'write_db')
private writeRepository: Repository<User>,
@InjectRepository(Log, 'log_db')
private logRepository: Repository<Log>
) {}
}
typescript
- 动态注入技巧
// 使用工厂模式动态选择Repository
getRepository(dbName: string): Repository<User> {
return this[`${dbName}Repository`];
}
typescript
💡 最佳实践:
- 为不同业务模块创建独立的Service类
- 使用
@InjectRepository
而非直接getRepository()
保证依赖注入 - 在单元测试中可mock特定连接的Repository
多实例操作验证进阶
- 端点设计规范
@Controller('users')
export class UserController {
@Get('read')
async getRead() {
return this.userService.readRepo.find();
}
@Get('write')
async getWrite() {
return this.userService.writeRepo.find();
}
}
typescript
- 测试验证方案
方法一:CURL测试
# 测试读库
curl -X GET http://localhost:3000/users/read
# 测试写库
curl -X GET http://localhost:3000/users/write
bash
方法二:自动化测试
describe('Multi DB Connection', () => {
let readRepo: Repository<User>;
let writeRepo: Repository<User>;
beforeEach(async () => {
readRepo = module.get(getRepositoryToken(User, 'read_db'));
writeRepo = module.get(getRepositoryToken(User, 'write_db'));
});
it('should query different dbs', async () => {
await readRepo.save({...}); // 写入读库
await writeRepo.save({...}); // 写入写库
const readData = await readRepo.find();
const writeData = await writeRepo.find();
expect(readData).not.toEqual(writeData);
});
});
typescript
- Swagger集成
@ApiQuery({ name: 'source', enum: ['read', 'write'] })
@Get()
async getUsers(@Query('source') source: string) {
return this.getRepo(source).find();
}
typescript
高级应用场景
- 读写分离实现
// 写操作强制使用主库
async createUser(dto: CreateUserDto) {
return this.writeRepository.save(dto);
}
// 读操作使用从库
async getUsers() {
return this.readRepository.find();
}
typescript
- 分库分表示例
@Injectable()
export class ShardingService {
constructor(
@InjectRepository(User, 'shard_0')
private shard0Repo: Repository<User>,
@InjectRepository(User, 'shard_1')
private shard1Repo: Repository<User>
) {}
getShardRepo(userId: number): Repository<User> {
return userId % 2 === 0 ? this.shard0Repo : this.shard1Repo;
}
}
typescript
- 事务处理方案
async transferFunds() {
const queryRunner = this.writeDataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.save(User, {...});
await queryRunner.manager.update(Account, {...});
await queryRunner.commitTransaction();
} catch (err) {
await queryRunner.rollbackTransaction();
throw err;
} finally {
await queryRunner.release();
}
}
typescript
常见问题排查
- 错误:RepositoryNotFoundError
- 检查实体是否在对应连接的entities数组中注册
- 确认连接名称拼写是否正确
- 错误:ConnectionNotFoundError
- 检查
forRoot
配置的name是否与注入时一致 - 确保模块加载顺序正确
- 性能优化建议
- 为高频访问的Repository添加缓存
- 使用
@Transaction
注解优化事务代码 - 考虑实现Repository的懒加载
// 懒加载示例
private get lazyRepo() {
return this.writeDataSource.getRepository(User);
}
typescript
通过以上扩展内容,开发者可以更全面地掌握TypeORM多数据库连接的注入机制,并能够应对各种复杂业务场景的需求。
动态路由方案 🚦
参数捕获层(增强版)
在动态路由场景中,我们可以通过多种方式获取路由参数,实现更灵活的控制:
- 多参数捕获
@Get('query')
async queryData(
@Query('db') dbName: string,
@Query('cache') useCache: boolean
) {
const repo = this.selectRepository(dbName);
return useCache ? this.cachedFind(repo) : repo.find();
}
typescript
- 参数验证与转换
import { IsIn, Transform } from 'class-validator';
class QueryParams {
@IsIn(['db1', 'db2', 'default'])
db: string;
@Transform(({ value }) => value === 'true')
cache: boolean;
}
@Get('safe-query')
async safeQuery(@Query() params: QueryParams) {
// 参数已自动验证和转换
}
typescript
- Header参数捕获
@Get('header-route')
async headerRoute(@Headers('x-db-source') dbSource: string) {
return this.selectRepository(dbSource).find();
}
typescript
智能仓库选择器(进阶实现)
- 加权路由选择
private selectRepository(name: string): Repository<User> {
const strategy = {
'db1': { repo: this.repo1, weight: 0.7 },
'db2': { repo: this.repo2, weight: 0.3 }
};
return this.getWeightedRepository(strategy, name);
}
private getWeightedRepository(strategy: any, name: string) {
if (name && strategy[name]) {
return Math.random() < strategy[name].weight
? strategy[name].repo
: this.defaultRepo;
}
return this.defaultRepo;
}
typescript
- 故障转移机制
private async selectWithFallback(name: string): Promise<Repository<User>> {
try {
const repo = this.selectRepository(name);
await repo.query('SELECT 1'); // 健康检查
return repo;
} catch {
return this.defaultRepo; // 自动降级
}
}
typescript
- 多租户支持
private selectByTenant(tenantId: string): Repository<User> {
const tenantMap = new Map([
['tenantA', this.repo1],
['tenantB', this.repo2]
]);
return tenantMap.get(tenantId) || this.defaultRepo;
}
typescript
可视化流程(增强版)
性能优化技巧
- 仓库缓存
private repositoryCache = new Map<string, Repository<User>>();
getCachedRepository(name: string): Repository<User> {
if (!this.repositoryCache.has(name)) {
this.repositoryCache.set(name, this.selectRepository(name));
}
return this.repositoryCache.get(name)!;
}
typescript
- 批量查询优化
@Post('batch-query')
async batchQuery(@Body() requests: {db: string, ids: number[]}[]) {
const results = await Promise.all(
requests.map(req =>
this.selectRepository(req.db)
.find({ where: { id: In(req.ids) }))
);
return results.flat();
}
typescript
- SQL日志标记
private getTaggedRepository(name: string) {
const repo = this.selectRepository(name);
repo.queryRunner.dataSource.setOptions({
logging: ['query'],
logger: new DebugLogger(name) // 自定义日志标记
});
return repo;
}
typescript
安全防护方案
- SQL注入防护
@Get('safe-find')
async safeFind(
@Query('db') dbName: string,
@Query('name') userName: string
) {
return this.selectRepository(dbName)
.createQueryBuilder()
.where("name = :name", { name: userName }) // 参数化查询
.getMany();
}
typescript
- 访问频率控制
@UseGuards(ThrottlerGuard)
@Get('throttled-query')
async throttledQuery(@Query('db') dbName: string) {
return this.selectRepository(dbName).find();
}
typescript
- 权限验证
@Get('admin-data')
@Roles('admin') // 自定义装饰器
async adminQuery(@Query('db') dbName: string) {
return this.selectRepository(dbName)
.find({ where: { sensitive: true } });
}
typescript
生产环境最佳实践
- 配置化路由规则
# config/routes.yaml
routes:
- path: /v1/api
db: db1
cache: true
- path: /v2/api
db: db2
yaml
- A/B测试集成
selectABTestRepository(): Repository<User> {
return this.abTest.isVariantA()
? this.repo1
: this.repo2;
}
typescript
- 监控指标埋点
private monitoredSelect(name: string) {
const start = Date.now();
const repo = this.selectRepository(name);
metrics.observe('db_select', Date.now() - start);
return repo;
}
typescript
通过以上扩展方案,动态路由系统可以具备:
- 智能流量分配能力
- 完善的故障恢复机制
- 细粒度的性能监控
- 企业级的安全防护
- 灵活的多租户支持
开发者可以根据实际业务需求,选择合适的实现策略组合。
架构级优化 🧩
拦截器方案(增强实现)
元数据驱动的智能路由
@Injectable()
export class DbInterceptor implements NestInterceptor {
constructor(private reflector: Reflector) {}
intercept(context: ExecutionContext, next: CallHandler) {
const request = context.switchToHttp().getRequest();
const dbMeta = this.reflector.get<DbRouteMeta>('database', context.getHandler());
request.dbContext = {
name: dbMeta?.strategy === 'QUERY'
? request.query.db
: dbMeta?.default || 'primary',
readOnly: dbMeta?.readOnly ?? false
};
return next.handle().pipe(
tap(() => metrics.recordDbAccess(request.dbContext))
);
}
}
// 使用装饰器定义路由策略
@DbRoute({ strategy: 'HEADER', default: 'replica' })
@Get('analytics')
getAnalytics() {
// 自动使用header中的x-db-source值
}
typescript
多维度路由决策
private determineDatabase(request: Request): string {
// 1. 优先级:强制覆盖标记
if (request.headers['x-db-force']) return request.headers['x-db-force'];
// 2. 业务分片规则
if (request.user?.tenantId) {
return this.shardingMap.get(request.user.tenantId.slice(-1));
}
// 3. 读写分离
return request.method === 'GET' ? 'replica' : 'primary';
}
typescript
性能优化技巧
// 使用WeakMap缓存数据源决策
private routeCache = new WeakMap<Request, string>();
intercept(context: ExecutionContext) {
const request = context.getArgByIndex(0);
if (!this.routeCache.has(request)) {
this.routeCache.set(request, this.determineDatabase(request));
}
// ...
}
typescript
动态模块工厂(生产级实现)
支持多实体注册
static forConnection(
name: string,
entities: EntityClass[],
config?: Partial<DataSourceOptions>
): DynamicModule {
const providers = entities.map(entity => ({
provide: getRepositoryToken(entity, name),
useFactory: (dataSource: DataSource) => dataSource.getRepository(entity),
inject: [getDataSourceToken(name)]
}));
return {
module: DatabaseModule,
providers: [
{
provide: getDataSourceToken(name),
useFactory: () => new DataSource({ name, ...defaultConfig, ...config }).initialize()
},
...providers
],
exports: providers
};
}
typescript
连接池生命周期管理
@Global()
@Module({})
export class DatabaseModule {
static async shutdown(moduleRef: ModuleRef) {
const connections = moduleRef['_imports']
.filter(m => m?.providers?.some(p => p?.provide?.toString().includes('DataSource')));
await Promise.all(
connections.map(async c => {
const token = c.providers.find(p => p.provide).provide;
const ds = await moduleRef.get(token, { strict: false });
await ds.destroy();
})
);
}
}
// 在main.ts中注册关闭钩子
app.enableShutdownHooks();
app.use(async () => {
await DatabaseModule.shutdown(app.select(DatabaseModule));
});
typescript
多租户动态注册
static registerTenant(tenantId: string, config: DataSourceOptions) {
const token = `TENANT_${tenantId}`;
return {
module: DatabaseModule,
providers: [{
provide: token,
useFactory: () => new DataSource({
...config,
name: token,
poolSize: 5 // 限制每个租户连接数
}).initialize()
}],
exports: [token]
};
}
typescript
混合架构方案
读写分离+分库分表集成
配置中心集成示例
static forConnectionAsync(name: string, options: {
configKey: string;
entities: EntityClass[];
}): DynamicModule {
return {
providers: [{
provide: getDataSourceToken(name),
useFactory: async (config: ConfigService) => {
const dbConfig = config.get(options.configKey);
return new DataSource({
name,
...dbConfig,
entities: options.entities
}).initialize();
},
inject: [ConfigService]
}]
};
}
typescript
性能优化矩阵
优化方向 | 技术方案 | 适用场景 | 收益预期 |
---|---|---|---|
连接复用 | 请求级数据源缓存 | 高并发查询 | 30% QPS提升 |
智能路由 | 基于SQL特征的读写分离 | 混合负载场景 | 降低主库压力40% |
预热加载 | 启动时初始化常用Repository | 冷启动敏感系统 | 减少首请求延迟200ms |
动态降级 | 熔断机制+本地缓存 | 数据库不可用场景 | 保障核心业务可用性 |
错误处理最佳实践
static forConnection(name: string, options: {
fallback?: boolean;
} = {}): DynamicModule {
return {
providers: [{
provide: getDataSourceToken(name),
useFactory: () => this.createDataSourceWithRetry(name, options.fallback),
}]
};
}
private static async createDataSourceWithRetry(name: string, fallback: boolean) {
let retries = 3;
while (retries--) {
try {
const ds = new DataSource({ name });
return await ds.initialize();
} catch (err) {
if (!retries) {
if (fallback) return this.createFallbackDataSource(name);
throw err;
}
await new Promise(r => setTimeout(r, 1000));
}
}
}
typescript
通过以上增强方案,系统可获得:
- 毫秒级动态路由决策能力
- 优雅的连接池生命周期管理
- 多租户场景下的资源隔离
- 生产级的故障恢复机制
- 细粒度的性能优化手段
生产环境最佳实践 🏆
配置中心集成(增强版)
多环境动态配置
TypeOrmModule.forRootAsync({
name: 'cluster_db',
useFactory: (config: ConfigService) => {
const env = config.get('NODE_ENV');
return {
type: 'mysql',
host: config.get(`${env}_DB_HOST`),
port: +config.get(`${env}_DB_PORT`),
username: config.get(`${env}_DB_USER`),
password: config.get(`${env}_DB_PASSWORD`),
synchronize: env === 'development',
extra: {
connectionLimit: env === 'production' ? 100 : 20
}
};
},
inject: [ConfigService]
});
typescript
密钥管理集成
useFactory: async (config: ConfigService, vault: SecretService) => ({
password: await vault.get('database-secret'),
ssl: {
ca: await vault.getCert('mysql-ca')
}
})
typescript
配置热更新
let config: DataSourceOptions;
setInterval(async () => {
const newConfig = await fetchConfigFromAPI();
if (JSON.stringify(config) !== JSON.stringify(newConfig)) {
await dataSource.destroy();
config = newConfig;
await dataSource.initialize();
}
}, 300000); // 每5分钟检查
typescript
连接池优化(深度调优)
多维度优化配置
# 生产环境推荐配置
database:
pool:
max: 100 # 最大连接数(根据CPU核心数×2)
min: 10 # 最小保持连接数
acquire: 30000 # 获取连接超时(ms)
idle: 60000 # 连接空闲时间(ms)
evict: 10000 # 驱逐检查间隔(ms)
diagnostics:
slowQueryThreshold: 200 # 慢查询阈值(ms)
logLevel: 'warn' # 日志级别
yaml
连接池监控面板
setInterval(() => {
const poolStats = dataSource.driver.pool;
metrics.gauge('db_pool_size', poolStats.size);
metrics.gauge('db_pool_available', poolStats.available);
metrics.gauge('db_pool_waiting', poolStats.waiting);
}, 5000);
typescript
连接泄漏检测
// 在全局异常过滤器添加
catch(err) {
if (err.message.includes('ConnectionAcquireTimeoutError')) {
alertOpsTeam('连接池泄漏风险!');
}
}
typescript
事务一致性策略(企业级方案)
增强型事务矩阵
方案 | 适用场景 | 实现复杂度 | 数据延迟 | 补救措施 |
---|---|---|---|---|
Saga模式 | 跨服务事务 | 高 | 分钟级 | 补偿事务 |
TCC模式 | 高一致性金融交易 | 很高 | 秒级 | 人工干预 |
本地消息表 | 订单支付场景 | 中 | 秒级 | 定时任务修复 |
两阶段提交 | 同数据库厂商跨库 | 低 | 毫秒级 | DBA介入 |
最终一致性 | 社交/日志系统 | 低 | 小时级 | 自动重试 |
Saga模式实现示例
class OrderSaga {
async execute() {
try {
await this.step1ReserveInventory();
await this.step2ChargePayment();
await this.step3CreateShipping();
} catch (err) {
await this.compensate();
}
}
private async compensate() {
// 逆向操作示例
await paymentService.refund();
await inventoryService.restock();
}
}
typescript
事务监控看板
// 事务拦截器
@Injectable()
export class TransactionMonitor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
const txId = generateTxId();
monitor.startTransaction(txId);
return next.handle().pipe(
tap(() => monitor.endTransaction(txId, 'success')),
catchError(err => {
monitor.endTransaction(txId, 'failed');
throw err;
})
);
}
}
typescript
灾备与高可用
多活数据中心配置
const primaryDS = new DataSource({
name: 'primary',
replication: {
master: { host: 'us-east-1.rds.amazonaws.com' },
slaves: [
{ host: 'us-west-1.rds.amazonaws.com' },
{ host: 'eu-central-1.rds.amazonaws.com' }
]
}
});
typescript
自动故障转移
// 健康检查中间件
app.use(async (req, res, next) => {
if (!primaryDS.isInitialized) {
await failoverToReplica();
}
next();
});
typescript
备份恢复策略
backup:
cron: "0 3 * * *" # 每天凌晨3点
retention: 35 # 保留35天
encryption: true # AES-256加密
verifyAfter: true # 备份后校验
yaml
性能压测指标
场景 | QPS(单节点) | 平均延迟 | 99分位延迟 | 推荐硬件配置 |
---|---|---|---|---|
纯读操作 | 12,000 | 23ms | 45ms | 4核8G + 10K IOPS |
读写混合(7:3) | 8,500 | 41ms | 89ms | 8核16G + 20K IOPS |
批量插入 | 3,200 | 120ms | 250ms | 16核32G + SSD |
通过以上增强方案,您的生产环境将获得:
- 智能动态配置能力
- 工业级连接池管理
- 企业级事务保障
- 多活容灾架构
- 可量化的性能基准
学习路径建议 📚
1. 基础练习(1小时)🔧
目标
- 掌握多数据库连接的基本配置
- 理解仓库注入的核心机制
详细任务清单
- 环境准备(15分钟)
- 使用Docker快速启动两个MySQL实例:
docker run --name mysql_primary -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0 docker run --name mysql_replica -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:8.0
bash - 创建测试数据库:
CREATE DATABASE shop_primary; CREATE DATABASE shop_replica;
sql
- 使用Docker快速启动两个MySQL实例:
- TypeORM配置(20分钟)
- 基础多连接配置:
// app.module.ts TypeOrmModule.forRoot({ name: 'primary', host: 'localhost', port: 3306, username: 'root', password: '123456', database: 'shop_primary', entities: [Product] }), TypeOrmModule.forRoot({ name: 'replica', host: 'localhost', port: 3307, username: 'root', password: '123456', database: 'shop_replica', entities: [Product] })
typescript
- 基础多连接配置:
- 仓库注入实践(25分钟)
- 实现双仓库服务:
@Injectable() export class ProductService { constructor( @InjectRepository(Product, 'primary') private primaryRepo: Repository<Product>, @InjectRepository(Product, 'replica') private replicaRepo: Repository<Product> ) {} async compareData() { const [primaryData, replicaData] = await Promise.all([ this.primaryRepo.find(), this.replicaRepo.find() ]); return { primaryData, replicaData }; } }
typescript
- 实现双仓库服务:
💡 扩展练习:尝试在compareData()
方法中添加数据同步逻辑,当主从数据不一致时自动修复。
2. 进阶实战(2小时)🚀
目标
- 实现智能路由决策
- 掌握拦截器的核心设计模式
详细任务清单
- 动态路由选择器(45分钟)
- 实现权重分配策略:
private selectRepo(userId: number): Repository<Product> { const isVip = userId % 5 === 0; // VIP用户走主库 return isVip ? this.primaryRepo : this.replicaRepo; }
typescript - 添加测试接口:
@Get(':userId') async getProducts(@Param('userId') userId: number) { return this.selectRepo(userId).find(); }
typescript
- 实现权重分配策略:
- 拦截器开发(1小时15分钟)
- 创建元数据驱动拦截器:
@Injectable() export class DbRoutingInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler) { const request = context.switchToHttp().getRequest(); request.dbContext = { isReadOnly: ['GET', 'HEAD'].includes(request.method), userId: request.user?.id }; return next.handle(); } }
typescript - 全局注册:
app.useGlobalInterceptors(new DbRoutingInterceptor());
typescript
- 创建元数据驱动拦截器:
💡 挑战任务:在拦截器中集成Redis缓存,对GET
请求实现自动缓存穿透保护。
3. 生产部署(1小时)🏭
目标
- 掌握环境变量管理规范
- 验证连接池性能极限
详细任务清单
- 环境变量配置(20分钟)
- 使用
dotenv
管理配置:# .env.production DB_HOST=cluster.rds.amazonaws.com DB_PORT=3306 DB_MAX_CONN=100
dotenv - 动态模块改造:
TypeOrmModule.forRootAsync({ useFactory: (config: ConfigService) => ({ host: config.get('DB_HOST'), extra: { connectionLimit: +config.get('DB_MAX_CONN') } }) })
typescript
- 使用
- 压力测试(40分钟)
- 使用
k6
进行基准测试:// stress-test.js import http from 'k6/http'; export const options = { vus: 50, // 并发用户数 duration: '1m' }; export default () => { http.get('http://localhost:3000/products'); };
javascript - 关键指标监控:
k6 run --out influxdb=http://monitor:8086/stress stress-test.js
bash
- 使用
💡 生产技巧:在docker-compose.yml
中配置资源限制,模拟生产环境约束:
services:
app:
deploy:
resources:
limits:
cpus: '2'
memory: 1GB
yaml
📌 学习资源推荐
- 官方文档
- 扩展工具
- 数据库监控:Prometheus + Grafana
- SQL分析:Percona PMM
- 实战项目
- 电商系统分库分表示例
- 多租户SAAS平台架构
通过这个渐进式学习路径,您将从基础配置逐步进阶到生产级部署,最终掌握企业级数据库架构的核心技能! 🎯
↑